package ink.metoo.gude.module.game.service.impl

import ink.metoo.gude.module.game.domain.GameLiarTavernEventType
import ink.metoo.gude.module.game.domain.GameLiarTavernException
import ink.metoo.gude.module.game.domain.ddl.GameRoom
import ink.metoo.gude.module.game.domain.ddl.GameType
import ink.metoo.gude.module.game.domain.model.GameLiarTavernData
import ink.metoo.gude.module.game.repository.GameEventRepository
import ink.metoo.gude.module.game.repository.GameRoomRepository
import ink.metoo.gude.module.game.service.GameLiarTavernCoreService
import ink.metoo.gude.module.game.util.createEvent
import ink.metoo.gude.module.security.domain.ddl.User
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

@Service
class GameLiarTavernCoreServiceImpl(
    override val gameRoomRepository: GameRoomRepository,
    override val gameEventRepository: GameEventRepository,
) : GameLiarTavernCoreService {

    private val gameDataMap = mutableMapOf<Long, GameLiarTavernData>()

    override val gameType = GameType.SCOUNDRELS_TAVERN

    fun GameRoom.data() =
        gameDataMap.compute(id ?: throw GameLiarTavernException(reason = "未知房间数据")) { key, value ->
            value ?: GameLiarTavernData(this)
        }!!


    override fun GameRoom.init() {
        minimum = 2
        maximum = 4
    }

    override fun GameRoom.start() {
        // 开始游戏
        createEvent(GameLiarTavernEventType.GAME_START, creator)
            .commit()
        refreshPlayerItems()
    }

    // 刷新物品
    fun GameRoom.refreshPlayerItems() {
        createEvent(GameLiarTavernEventType.REFRESH_ITEM, null)
            .commit()
    }

    /**
     * 玩家加入游戏
     */
    @Transactional
    override fun User.join(gr: GameRoom) {
        val data = gr.data()
        when (gr.status) {

            GameRoom.Status.WAIT -> {
                val players = data.players
                if (players.size in gr.minimum!!..gr.maximum!!) {
                    players.add(GameLiarTavernData.Player(this))
                    gr.createEvent(GameLiarTavernEventType.PLAYER_JOIN, this)
                        .commit()
                } else {
                    // 对局玩家已满则加入到观战当中
                    watch(gr)
                }
            }

            GameRoom.Status.IN_PROGRESS -> {
                watch(gr)
            }

            GameRoom.Status.FINISH -> {
                throw GameLiarTavernException(gr.id, "游戏已经结束")
            }

            else -> {}
        }
    }

    /**
     * 玩家离开游戏
     */
    @Transactional
    override fun User.leave(gr: GameRoom) {
        val data = gr.data()
        when (gr.status) {

            GameRoom.Status.WAIT -> {
                data.players.removeIf { it.user.id == id }
                data.watchUsers.remove(this)
                gr.createEvent(GameLiarTavernEventType.PLAYER_LEAVE, this)
                    .commit()
            }

            GameRoom.Status.IN_PROGRESS -> {
                val player = data.players.findLast { it.user.id == id }
                if (player != null) {

                } else {

                }
            }

            GameRoom.Status.FINISH -> {
                throw GameLiarTavernException(gr.id!!, "游戏已经结束")
            }

            else -> {}
        }

    }

    /**
     * 玩家观战游戏
     */
    override fun User.watch(gr: GameRoom) {
        gr.createEvent(GameLiarTavernEventType.PLAYER_WATCH, this)
            .commit()
    }

    /**
     * 玩家执行动作
     */
    override fun User.onAction(
        gr: GameRoom,
        action: String
    ) {
        TODO("Not yet implemented")
    }


}